<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
 <xsl:output method="text" />  
 
 <!-- parameter for "ignoring white-space only text nodes" during comparison -->
 <!-- if iws='y', "white-space only text nodes" will not be considered during comparison  -->
 <xsl:template match="files">
 <xsl:for-each select="file">
 <xsl:param name="iws" />
 <xsl:param name ="f1" select="'transform.xsl'"/>
 <xsl:param name ="f2" select="'transform.xsl'"/>
 <xsl:variable name="doc1" select="document($f1)" />
 <xsl:variable name="doc2" select="document($f2)" />
 
 <xsl:template match="/">
 
    <!-- store hash of 1st document into a variable; it is concatenation of name and values of all nodes -->
    <xsl:variable name="one">
      <xsl:for-each select="$doc1//@*">
        <xsl:sort select="name()" />
        <xsl:variable name="expr">
             <xsl:call-template name="constructXPathExpr">
                 <xsl:with-param name="node" select=".." />
                 <xsl:with-param name="xpath" select="name(..)" />
             </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="concat($expr,'/@',name(),':',.)" />:<xsl:value-of select="count(../ancestor-or-self::node() | ../preceding::node())" /> 
      </xsl:for-each>
      <xsl:choose>
         <xsl:when test="$iws='y'">
           <xsl:for-each select="$doc1//node()[not(normalize-space(self::text()) = '')]">
             <xsl:variable name="expr">
                 <xsl:call-template name="constructXPathExpr">
                    <xsl:with-param name="node" select="ancestor-or-self::*[1]" />
                    <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" />
                 </xsl:call-template>
             </xsl:variable>
             <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" />  
           </xsl:for-each>
         </xsl:when>
         <xsl:otherwise>
           <xsl:for-each select="$doc1//node()">
              <xsl:variable name="expr">
                  <xsl:call-template name="constructXPathExpr">
                      <xsl:with-param name="node" select="ancestor-or-self::*[1]" />
                      <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" />
                  </xsl:call-template>
             </xsl:variable>
             <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" />  
           </xsl:for-each>
         </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>  
    
    <!-- store hash of 2nd document into a variable; it is concatenation of name and values of all nodes -->
    <xsl:variable name="two">
      <xsl:for-each select="$doc2//@*">
        <xsl:sort select="name()" />
        <xsl:variable name="expr">
            <xsl:call-template name="constructXPathExpr">
                 <xsl:with-param name="node" select=".." />
                 <xsl:with-param name="xpath" select="name(..)" />
            </xsl:call-template>
         </xsl:variable>
         <xsl:value-of select="concat($expr,'/@',name(),':',.)" />:<xsl:value-of select="count(../ancestor-or-self::node() | ../preceding::node())" />  
      </xsl:for-each>
      <xsl:choose>
         <xsl:when test="$iws='y'">
           <xsl:for-each select="$doc2//node()[not(normalize-space(self::text()) = '')]">
                 <xsl:variable name="expr">
                     <xsl:call-template name="constructXPathExpr">
                         <xsl:with-param name="node" select="ancestor-or-self::*[1]" />
                         <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" />
                    </xsl:call-template>
                 </xsl:variable>
                 <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" />  
           </xsl:for-each>
         </xsl:when>
         <xsl:otherwise>
           <xsl:for-each select="$doc2//node()">
                <xsl:variable name="expr">
                    <xsl:call-template name="constructXPathExpr">
                        <xsl:with-param name="node" select="ancestor-or-self::*[1]" />
                        <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" />
                    </xsl:call-template>
                </xsl:variable>
                <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" />  
           </xsl:for-each>
         </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>  
    <xsl:choose>
      <xsl:when test="$one = $two">
          Equal 
      </xsl:when>
      <xsl:otherwise>
          Not equal        
      </xsl:otherwise>
    </xsl:choose>
 </xsl:template>
 
 <!-- template to construct an XPath expression, for a given element node -->
 <xsl:template name="constructXPathExpr">
   <xsl:param name="node" />
   <xsl:param name="xpath" />
      
   <xsl:choose>       
     <xsl:when test="$node/parent::*">
       <xsl:call-template name="constructXPathExpr">
            <xsl:with-param name="node" select="$node/parent::*" />
            <xsl:with-param name="xpath" select="concat(name($node/parent::*),'/',$xpath)" />
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="concat('/',$xpath)" />
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>